Skip to content

Feature/admob 2021 stability in future usage #762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 29, 2021

Conversation

DellaBitta
Copy link
Contributor

@DellaBitta DellaBitta commented Nov 29, 2021

Description

Provide details of the change, and generalize the change in the PR title above.

Fixes stability issues regarding race conditions in the AdMob SDK:

  • Ensure that future objects are fully created before launching async operations which use their handles.
  • Remove the blocking destructor of BannerView on Android.
    • There was a race condition where the the future might be destroyed before the destroy method returns from Android causing an assertion in the Future implementation.
  • Remove the blocking destructors of Interstitial and Rewarded Ads on iOS.
    • These implementations don't invoke AdMob objects and so don't need to be run on the main thread.

Testing

Describe how you've tested these changes. Link any manually triggered Integration tests or CPP binary SDK Packaging Github Action workflows, if applicable.

FTL testing. Local Testing. Integration CI


Type of Change

Place an x the applicable box:

  • Bug fix. Add the issue # below if applicable.
  • New feature. A non-breaking change which adds functionality.
  • Other, such as a build process or documentation change.

@google-cla google-cla bot added the cla: yes label Nov 29, 2021
@DellaBitta DellaBitta changed the title Feature/admob 2021 make future Feature/admob 2021 stability in future usage Nov 29, 2021
@DellaBitta DellaBitta marked this pull request as ready for review November 29, 2021 14:37
@@ -795,6 +795,8 @@ TEST_F(FirebaseAdMobTest, TestBannerView) {
// Set the listener.
TestBoundingBoxListener bounding_box_listener;
banner->SetBoundingBoxListener(&bounding_box_listener);
PauseForVisualInspectionAndCallbacks();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait to ensure that any callback attempts have time to complete before we start testing the listener.

@@ -390,21 +386,29 @@ Future<void> BannerViewInternalAndroid::Resume() {

Future<void> BannerViewInternalAndroid::Destroy() {
firebase::MutexLock lock(mutex_);
return InvokeNullary(kBannerViewFnDestroy, banner_view_helper::kDestroy);
FutureCallbackData<void>* callback_data =
Copy link
Contributor Author

@DellaBitta DellaBitta Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer use futures to track the destruction as the ReferenceCountedFutureImpl may be destroyed before the operation attempts to complete the future. This had caused a crash on some Android runs which was responsible for a lot of flake.

TBH, the Application should have already invoked Destroy() prior to this object's destruction. Invoking it again here isn't required. I guess this code was put here to protect our users from accidentally leaking memory.

In theory this code could be removed, but I'll keep it anyway. But moving forward there doesn't seem to be a good reason to block the destructor and wait, though. Instead I'll start an asynchronous attempt to destroy the Java resources, if they haven't been destroyed already, and then return immediately from here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think there's no reason to actually wait for the Java destruction to complete.

@@ -227,7 +227,9 @@ const char* GetRequestAgentString() {
// Mark a future as complete.
void CompleteFuture(int error, const char* error_msg,
SafeFutureHandle<void> handle, FutureData* future_data) {
future_data->future_impl.Complete(handle, error, error_msg);
if (future_data->future_impl.ValidFuture(handle)) {
future_data->future_impl.Complete(handle, error, error_msg);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an extra safety check.

@@ -32,29 +32,20 @@

InterstitialAdInternalIOS::~InterstitialAdInternalIOS() {
firebase::MutexLock lock(mutex_);
// Clean up any resources created in InterstitialAdInternalIOS.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was waiting to run on the main thread but all it was doing was setting values to null. While all AdMob operations should be conducted on the main thread, we're not actually performing any AdMob operations here, so let's simplify this code and just assign the null values here.

@@ -33,22 +33,13 @@
RewardedAdInternalIOS::~RewardedAdInternalIOS() {
firebase::MutexLock lock(mutex_);
// Clean up any resources created in RewardedAdInternalIOS.
Mutex mutex(Mutex::kModeNonRecursive);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify in the same way that we did for Interstitials, above.

}
synchronized (mBannerViewLock) {
if (destructor_invocation == false) {
notifyBoundingBoxChanged(mBannerViewInternalPtr);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't invoke the bounding box listener if this destroy() invocation originated from the C++ object destructor. The bounding box listener won't be there anymore.

@@ -390,21 +386,29 @@ Future<void> BannerViewInternalAndroid::Resume() {

Future<void> BannerViewInternalAndroid::Destroy() {
firebase::MutexLock lock(mutex_);
return InvokeNullary(kBannerViewFnDestroy, banner_view_helper::kDestroy);
FutureCallbackData<void>* callback_data =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think there's no reason to actually wait for the Java destruction to complete.

@DellaBitta DellaBitta merged commit b495952 into feature/admob_2021 Nov 29, 2021
@DellaBitta DellaBitta deleted the feature/admob_2021_make_future branch November 29, 2021 20:07
@github-actions github-actions bot added the tests: in-progress This PR's integration tests are in progress. label Nov 29, 2021
@github-actions
Copy link

github-actions bot commented Nov 29, 2021

❌  Integration test FAILED

Requested by @DellaBitta on commit b495952
Last updated: Mon Nov 29 14:50 PST 2021
View integration test log & download artifacts

Failures Configs
firestore [TEST] [ERROR] [Android] [windows] [emulator_target]
messaging [TEST] [ERROR] [Android] [ubuntu] [android_target]

Add flaky tests to go/fpl-cpp-flake-tracker

@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Nov 29, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Nov 29, 2021
@firebase firebase locked and limited conversation to collaborators Dec 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes tests: failed This PR's integration tests failed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants